#include "wk_usart.h"
#include "cdc_msc_class.h"
#include "wk_system.h"

volatile uint32_t rx1_count;
volatile uint32_t rx1_flag;

uint8_t uart1_rx_buffer[UART1_RX_BUFFER_SIZE];
uint8_t uart1_tx_buffer[UART1_TX_BUFFER_SIZE];

volatile uint32_t rx5_count;
volatile uint32_t rx5_flag;

uint8_t uart5_rx_buffer[UART5_RX_BUFFER_SIZE];
uint8_t uart5_tx_buffer[UART5_TX_BUFFER_SIZE];


#if (__ARMCC_VERSION > 6000000)
  __asm (".global __use_no_semihosting\n\t");
  void _sys_exit(int x)
  {
    x = x;
  }
  /* __use_no_semihosting was requested, but _ttywrch was */
  void _ttywrch(int ch)
  {
    ch = ch;
  }
  
  struct __FILE
  {
    int handle;
  };
  FILE __stdout;
  
  
#else
 #ifdef __CC_ARM
  #pragma import(__use_no_semihosting)
  struct __FILE
  {
    int handle;
  };
  FILE __stdout;
  void _sys_exit(int x)
  {
    x = x;
  }
  /* __use_no_semihosting was requested, but _ttywrch was */
  void _ttywrch(int ch)
  {
    ch = ch;
  }
 #endif
#endif

int fputc(int ch, FILE *f)
{
#if UART_DEBUG    
    while((USART1->sts & USART_TDBE_FLAG) == RESET);
    USART1->dt = ch;
#endif
    return ch;
}

void uart1_send_bytes(const uint8_t *byte, uint32_t len)
{
    for(int i=0; i<len; i++)
    {
        while((USART1->sts & USART_TDBE_FLAG) == RESET);
        USART1->dt = byte[i];
    }
}

void uart5_send_bytes(const uint8_t *byte, uint32_t len)
{
    for(int i=0; i<len; i++)
    {
        while((UART5->sts & USART_TDBE_FLAG) == RESET);
        UART5->dt = byte[i];
    }
}

void uart1_dma_send_bytes(const uint8_t *byte, uint32_t len)
{
    int enter_retry = 300;
    do
    {
        if((DMA1_CHANNEL3->ctrl & 0x01) == 0)
        {
            DMA1_CHANNEL3->dtcnt = len;
            DMA1_CHANNEL3->maddr = (uint32_t)byte;
            DMA1_CHANNEL3->ctrl_bit.chen = TRUE;
            break;
        }
        delay_100us(1);
    }while(enter_retry --);
}

void uart5_dma_send_bytes(const uint8_t *byte, uint32_t len)
{
    int enter_retry = 300;
    do
    {
        if((DMA1_CHANNEL4->ctrl & 0x01) == 0)
        {
            DMA1_CHANNEL4->dtcnt = len;
            DMA1_CHANNEL4->maddr = (uint32_t)byte;
            DMA1_CHANNEL4->ctrl_bit.chen = TRUE;
            break;
        }
        delay_100us(1);
    }while(enter_retry --);
}


/**
  * @brief  init usart1 function
  * @param  none
  * @retval none
  */
void wk_usart1_init(void)
{
  /* add user code begin usart1_init 0 */

  /* add user code end usart1_init 0 */

  gpio_init_type gpio_init_struct;
  gpio_default_para_init(&gpio_init_struct);

  /* add user code begin usart1_init 1 */
  dma_init_type dma_init_struct;

  dma_reset(DMA1_CHANNEL1);
  dma_default_para_init(&dma_init_struct);
  dma_init_struct.buffer_size = sizeof(uart1_rx_buffer)/sizeof(uart1_rx_buffer[0]);
  dma_init_struct.direction = DMA_DIR_PERIPHERAL_TO_MEMORY;
  dma_init_struct.memory_base_addr = (uint32_t)uart1_rx_buffer;
  dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_BYTE;
  dma_init_struct.memory_inc_enable = TRUE;
  dma_init_struct.peripheral_base_addr = (uint32_t)&USART1->dt;
  dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_BYTE;
  dma_init_struct.peripheral_inc_enable = FALSE;
  dma_init_struct.priority = DMA_PRIORITY_LOW;
  dma_init_struct.loop_mode_enable = FALSE;
  dma_init(DMA1_CHANNEL1, &dma_init_struct);
  
  dma_flexible_config(DMA1, FLEX_CHANNEL1, DMA_FLEXIBLE_UART1_RX);
  
  dma_reset(DMA1_CHANNEL3);
  dma_default_para_init(&dma_init_struct);
  dma_init_struct.buffer_size = sizeof(uart1_tx_buffer)/sizeof(uart1_tx_buffer[0]);
  dma_init_struct.direction = DMA_DIR_MEMORY_TO_PERIPHERAL;
  dma_init_struct.memory_base_addr = (uint32_t)uart1_tx_buffer;
  dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_BYTE;
  dma_init_struct.memory_inc_enable = TRUE;
  dma_init_struct.peripheral_base_addr = (uint32_t)&USART1->dt;
  dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_BYTE;
  dma_init_struct.peripheral_inc_enable = FALSE;
  dma_init_struct.priority = DMA_PRIORITY_LOW;
  dma_init_struct.loop_mode_enable = FALSE;
  dma_init(DMA1_CHANNEL3, &dma_init_struct);
  
  dma_flexible_config(DMA1, FLEX_CHANNEL3, DMA_FLEXIBLE_UART1_TX);
  /* add user code end usart1_init 1 */

  /* configure the TX pin */
  gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
  gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
  gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
  gpio_init_struct.gpio_pins = GPIO_PINS_9;
  gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
  gpio_init(GPIOA, &gpio_init_struct);
  
  /* configure the RX pin */
  gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
  gpio_init_struct.gpio_out_type  = GPIO_OUTPUT_PUSH_PULL;
  gpio_init_struct.gpio_mode = GPIO_MODE_INPUT;
  gpio_init_struct.gpio_pins = GPIO_PINS_10;
  gpio_init_struct.gpio_pull = GPIO_PULL_UP;
  gpio_init(GPIOA, &gpio_init_struct);
  
  /* configure param */
  usart_init(USART1, 115200, USART_DATA_8BITS, USART_STOP_1_BIT);
  usart_transmitter_enable(USART1, TRUE);
  usart_receiver_enable(USART1, TRUE);
  usart_parity_selection_config(USART1, USART_PARITY_NONE);

  usart_hardware_flow_control_set(USART1, USART_HARDWARE_FLOW_NONE);

  /* add user code begin usart1_init 2 */
  usart_dma_receiver_enable(USART1, TRUE);
  usart_dma_transmitter_enable(USART1, TRUE);
  usart_flag_clear(USART1, USART_IDLEF_FLAG);
  usart_interrupt_enable(USART1, USART_IDLE_INT, TRUE);
  
  /* add user code end usart1_init 2 */
  usart_enable(USART1, TRUE);

  /* add user code begin usart1_init 3 */
  dma_channel_enable(DMA1_CHANNEL1, TRUE);
  dma_flag_clear(DMA1_FDT1_FLAG);
  dma_interrupt_enable(DMA1_CHANNEL1, DMA_FDT_INT, TRUE);
  dma_flag_clear(DMA1_FDT3_FLAG);
  dma_interrupt_enable(DMA1_CHANNEL3, DMA_FDT_INT, TRUE);
  /* add user code end usart1_init 3 */
}

/**
  * @brief  init uart5 function
  * @param  none
  * @retval none
  */
void wk_uart5_init(void)
{
  /* add user code begin uart5_init 0 */

  /* add user code end uart5_init 0 */

  gpio_init_type gpio_init_struct;
  gpio_default_para_init(&gpio_init_struct);

  /* add user code begin uart5_init 1 */
  dma_init_type dma_init_struct;

  dma_reset(DMA1_CHANNEL2);
  dma_default_para_init(&dma_init_struct);
  dma_init_struct.buffer_size = sizeof(uart5_rx_buffer)/sizeof(uart5_rx_buffer[0]);
  dma_init_struct.direction = DMA_DIR_PERIPHERAL_TO_MEMORY;
  dma_init_struct.memory_base_addr = (uint32_t)uart5_rx_buffer;
  dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_BYTE;
  dma_init_struct.memory_inc_enable = TRUE;
  dma_init_struct.peripheral_base_addr = (uint32_t)&UART5->dt;
  dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_BYTE;
  dma_init_struct.peripheral_inc_enable = FALSE;
  dma_init_struct.priority = DMA_PRIORITY_LOW;
  dma_init_struct.loop_mode_enable = FALSE;
  dma_init(DMA1_CHANNEL2, &dma_init_struct);
  
  dma_flexible_config(DMA1, FLEX_CHANNEL2, DMA_FLEXIBLE_UART5_RX);
  
  dma_reset(DMA1_CHANNEL4);
  dma_default_para_init(&dma_init_struct);
  dma_init_struct.buffer_size = sizeof(uart5_tx_buffer)/sizeof(uart5_tx_buffer[0]);
  dma_init_struct.direction = DMA_DIR_MEMORY_TO_PERIPHERAL;
  dma_init_struct.memory_base_addr = (uint32_t)uart5_tx_buffer;
  dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_BYTE;
  dma_init_struct.memory_inc_enable = TRUE;
  dma_init_struct.peripheral_base_addr = (uint32_t)&UART5->dt;
  dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_BYTE;
  dma_init_struct.peripheral_inc_enable = FALSE;
  dma_init_struct.priority = DMA_PRIORITY_LOW;
  dma_init_struct.loop_mode_enable = FALSE;
  dma_init(DMA1_CHANNEL4, &dma_init_struct);
  
  dma_flexible_config(DMA1, FLEX_CHANNEL4, DMA_FLEXIBLE_UART5_TX);
  /* add user code end uart5_init 1 */

  /* configure the TX pin */  
  gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
  gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
  gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
  gpio_init_struct.gpio_pins = GPIO_PINS_12;
  gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
  gpio_init(GPIOC, &gpio_init_struct);
  
  /* configure the RX pin */
  gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
  gpio_init_struct.gpio_mode = GPIO_MODE_INPUT;
  gpio_init_struct.gpio_pins = GPIO_PINS_2;
  gpio_init_struct.gpio_pull = GPIO_PULL_UP;
  gpio_init(GPIOD, &gpio_init_struct);
  
  gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
  gpio_init_struct.gpio_out_type  = GPIO_OUTPUT_PUSH_PULL;
  gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
  gpio_init_struct.gpio_pins = GPIO_PINS_8;     // DB_EN
  gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
  gpio_init(GPIOB, &gpio_init_struct);
  
  gpio_bits_set(GPIOB, GPIO_PINS_8);

  /* configure param */
  usart_init(UART5, 115200, USART_DATA_8BITS, USART_STOP_1_BIT);
  usart_transmitter_enable(UART5, TRUE);
  usart_receiver_enable(UART5, TRUE);
  usart_parity_selection_config(UART5, USART_PARITY_NONE);

  usart_hardware_flow_control_set(UART5, USART_HARDWARE_FLOW_NONE);

  /* add user code begin uart5_init 2 */
  usart_dma_receiver_enable(UART5, TRUE);
  usart_dma_transmitter_enable(UART5, TRUE);
  usart_flag_clear(UART5, USART_IDLEF_FLAG);
  usart_interrupt_enable(UART5, USART_IDLE_INT, TRUE);
  
  /* add user code end uart5_init 2 */
  usart_enable(UART5, TRUE);

  /* add user code begin uart5_init 3 */
  dma_channel_enable(DMA1_CHANNEL2, TRUE);
  dma_flag_clear(DMA1_FDT2_FLAG);
  dma_interrupt_enable(DMA1_CHANNEL2, DMA_FDT_INT, TRUE);
  dma_flag_clear(DMA1_FDT4_FLAG);
  dma_interrupt_enable(DMA1_CHANNEL4, DMA_FDT_INT, TRUE);
  /* add user code end uart5_init 3 */
}

/* add user code begin 1 */

void usb_usart_config( linecoding_type linecoding)
{
    // usart_init(USART1, linecoding.bitrate, linecoding.data, linecoding.format);
    // usart_parity_selection_config(USART1, linecoding.parity);
}



/* add user code end 1 */
